using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
using System.Reflection;
using Pampa.CRUD.Exceptions;

using Pampa.CRUD.Configuration.Validations;

namespace Pampa.CRUD.Configuration
{
    /// <summary>
    /// Esta clase representa la definicion de un item a editar en el CRUD de una entidad
    /// </summary>
    public abstract class EditItem : VisibleItem
    {
        List<Validation> validations;
        string onClientChange;

        public EditItem() : base()
        {
            validations = new List<Validation>();
        }

        public EditItem(EditItem sourceItem) : base(sourceItem)
        {
            validations = new List<Validation>(); 
            
            this.OnClientChange = sourceItem.OnClientChange;
            
            foreach (Validation validation in this.Validations)
            {
                this.Validations.Add(validation);
            }
        }

        #region Properties

        public abstract Type ValueTypeDefault { get; }

        public string OnClientChange
        {
            get { return onClientChange; }
            set { onClientChange = value; }
        }

        /// <summary>
        /// Validaciones asociadas al item de edicion
        /// </summary>
        public List<Validation> Validations
        {
            get { return validations; }
        }

        /// <summary>
        /// Indica si el campo es oblegatorio. Si tiene una validacion asociada de tipo RequiredValidation.
        /// </summary>
        public bool IsMandatory
        {
            get 
            {
                bool value = false;

                foreach (Validation validation in Validations)
                {
                    value = value || (validation is RequiredValidation);
                }

                return value;
            }
        }
        
        #endregion

        #region Public Functions

        public new static EditItem LoadFromXml(XmlNode node)
        {
            Item item = Item.LoadFromXml(node);

            if(item is EditItem)
            {
                EditItem editItem = (EditItem)item;
                return editItem;
            }
            else
            {
                throw (new ConfigurationException("There is no EditItem of Type " + node.Name));
            }
        }

        public override void LoadXml(XmlNode node)
        {
            try
            {
                base.LoadXml(node);

                if (node.Attributes["OnClientChange"] != null)
                    this.OnClientChange = node.Attributes["OnClientChange"].Value;

                XmlNode nodoValidations = ConfigurationManager.GetChildNode(node, "Validations");
                
                if (nodoValidations != null)
                {
                    Assembly assembly = Assembly.GetAssembly(typeof(Validation));
                                        
                    foreach (XmlNode nodoHijo in nodoValidations.ChildNodes)
                    {
                        Validation validation = (Validation)assembly.CreateInstance("Pampa.CRUD.Configuration.Validations." + nodoHijo.Name);
                        validation.LoadXml(nodoHijo);
                        Validations.Add(validation);
                    }
                }                
            }
            catch (Exception ex)
            {
                throw new Pampa.CRUD.Exceptions.ConfigurationException("Item " + this.Id + " mal definido.", ex);
            }
        }

        #endregion
    }
}
